Dålig kontra bra programkod
När man skriver program finns det saker som är möjligt att göra och
det finns saker som är bra att göra. De exempel som finns nedan
visar på saker som man "kan" skriva i Ada, men som kanske inte är så
bra och dessutom en variant som är vettig att skriva istället.
En viktig sak att förstå är att "bara för att man kan" skriva på ett
sätt är det kanske inte vettigt att göra detta. Det finns fall där
det "sämre" alternativet är vettigt att använda, men i denna kurs är
vi inte ute efter specialfallen utan vi vill att ni skriver kod med
i första hand läsbarhet och tydlighet som fokus.
När man skriver sitt program skall man tänka på att det är viktigt
att kunna läsa sitt (eller andras) program smidigt. Läsbarhet är
något som underskattas väldigt mycket (speciellt när man är ny på
detta med programmering). En van programmerare vet att man sparar
tid på att lägga den extra lilla tid det tar att göra det snyggt
från början.
Här finns ett antal exempel som visar hur man "inte skall skriva"
och hur man "skall skriva". Diskussioner om dessa varianter är det
bra att prata med assistenten om.
OBS! I uppgift Ada.O1.1 skall man INTE använda någon "loop". Där
får t.ex. "duplicering av kod" finnas.
Flera satser på samma rad
Att skriva flera satser på samma rad ställer till det för en
programmerare som är van. Man läser nämligen generellt sett bara i
vänsterkanten i koden för att hitta det man söker.
Hur man inte bör skriva
|
Hur man bör skriva
|
Put("Mata in ett heltal: "); Get(I);
|
Put("Mata in ett heltal: ");
Get(I);
|
Put("En text."); New_Line;
|
Put("En text.");
New_Line;
-- Eller i detta specialfall (med
-- "String" som utskriftsdatatyp).
Put_Line("En text.");
|
X := 2; Y := 5 * X; Z := X * Y;
|
X := 2;
Y := 5 * X;
Z := X * Y;
|
if A = 1 then Put("Text");
end if;
while B < 3 loop Do_The_Thing;
end loop;
procedure Huvudprogram is
C : Character;
begin Get(C);
end Huvudprogram;
|
-- Kontrollsatser, (under)program, mm. ska skrivas på
-- "rätt" sätt, bla. genom att inte blanda deras delar
-- med andra satser på samma rad
if A = 1 then
Put("Text");
end if;
while B < 3 loop
Do_The_Thing;
end loop;
procedure Huvudprogram is
C : Character;
begin
Get(C);
end Huvudprogram;
|
Indentering (ger mycket mer läsbarhet om man gör det bra)
Att inte indentera (skjut in sin kod på raden) på ett strukturerat
sätt gör att det blir svårt att läsa programmet. Man förlorar
mycket tid på att själv inte se vad man skrivit så gör det hela
tiden (går enkelt att fixa med "TAB" i Emacs om man har "Ada-mode"
påslaget.
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Ingen indentering alls.
procedure Name is
A : Integer;
B : Float;
begin
Put("...");
Get(A);
if A > 10 then
Put("Större än");
else
Put("Mindre än eller lika med");
end if;
end Name;
-- Felaktig indentering.
procedure Name is
A : Integer;
B : Float;
begin
Put("...");
Get(A);
if A > 10 then
Put("Större än");
else
Put("Mindre än eller lika med");
end if;
end Name;
|
-- TIPS: Följ det som ges som exempel i kursen.
-- Mycket mer läsbart. Följer den kodstandard
-- som är i Ada.
procedure Name is
A : Integer;
B : Float;
begin
Put("...");
Get(A);
if A > 10 then
Put("Större än");
else
Put("Mindre än eller lika med");
end if;
end Name;
|
-- Svårlästa paketinkludering.
-- Exempel 1:
with PAKET1; with PAKET2;
use PAKET1; use PAKET2;
with PAKET3; use PAKET3;
-- Exempel 2:
with PAKET1, PAKET2;
use PAKET1, PAKET2;
with PAKET3; with PAKET3;
|
-- Lättare att läsa.
with PAKET1; use PAKET1;
with PAKET2; use PAKET2;
with PAKET3; use PAKET3;
OBS! Lätt att plocka bort paket som inte används
och dessutom lätt att se att man gjort både "with"
och "use" på paketen. Läsbar kod gör att man
dessutom inte gör fel som i exempel 2 till vänster.
|
"Tät kod" eller "gles kod" och lite "stil" på programmet och "rätt ordning"
Hur gör jag min kod med tydlig med hjälp av lite extra "space"?
Tänk inte MYCKET "space" utan lagom.
Hur man inte bör skriva
|
Hur man bör skriva
|
x:=3.2*Sin(x)+7.5*Cos(X)/1.2*4.5;
|
x := 3.2 * Sin(x) + 7.5 * Cos(X) / 1.2 * 4.5;
|
Put("Mata in. ");
Get(I);
Put("Du skrev in: ");
Put(I);
Skip_Line;
New_Line;
Put("Mata in. ");
Get(F);
Put("Du skrev in: ");
Put(F);
New_Line;
Skip_Line;
|
-- Heltal
Put("Mata in. ");
Get(I);
Skip_Line; -- OBS! Denna hör ihop med "Get".
Put("Du skrev in: ");
Put(I);
New_Line;
-- Flyttal
Put("Mata in. ");
Get(F);
Skip_Line; -- OBS! Denna hör ihop med "Get".
Put("Du skrev in: ");
Put(F);
New_Line;
|
Put("Mata in. ");
Get(I);
Put("Du skrev in: ");
Put(I);
Skip_Line;
New_Line;
Put("Mata in. ");
Get(F);
Put("Du skrev in: ");
Put(F);
New_Line;
Skip_Line;
|
-- Heltal
Put("Mata in. ");
Get(I);
Skip_Line; -- OBS! Denna hör ihop med "Get".
Put("Du skrev in: ");
Put(I);
New_Line;
-- Flyttal
Put("Mata in. ");
Get(F);
Skip_Line; -- OBS! Denna hör ihop med "Get".
Put("Du skrev in: ");
Put(F);
New_Line;
|
Onaturligt formulerade "if"-satser
När det gäller "if"-satser ser man väldigt ofta konstruktioner som
är "onaturliga". Detta beror antagligen på attt man vill vara
säker på att man får rtt värde, men det visar på att man inte
riktigt har fårstått hur villkoren i "if"-satsen fungerar.
Ett villkor (mellan t.ex. "if" och "then") skall ha ett resultat
som är ett "booleskt värde" och om detta värde är True så
kommer den grenen att utföras. Man behöver alltså inte testa om
detta är lika med True eller False igen.
För läsbarhet är det dessutom viktigt att skriva "if"-satsen med
rätt stil, exempelvis med "if", "villkor" och "then" på egen rad så som
skrivet nedan. Se exemplen nedan för rätt stil.
Hur man inte bör skriva
|
Hur man bör skriva
|
if VILLKOR = True then
|
if VILLKOR then
|
if VILLKOR = False then
|
if not VILLKOR then
|
if VILLKOR then
...;
elsif not VILLKOR then
...;
end if;
|
if VILLKOR then
...;
else
...;
end if;
|
if VILLKOR_1 then
...;
elsif not VILLKOR_1 and VILLKOR_2 then
...;
elsif not VILLKOR_1 and not VILLKOR_2 then
...;
end if;
|
if VILLKOR_1 then
...;
elsif VILLKOR_2 then
...;
else
...;
end if;
|
-- Om man vill testa flera saker som beror av
-- varandra.
-- HÄR ÄR DET IBLAND SVÅRT ATT HITTA SINA FEL
-- (om man t.ex. gör saker i en tidigare "if"
-- som påverkar resultatet av vilkoren senare!
if VILLKOR_1 then
...;
end if;
if not VILLKOR_1 and VILLKOR_2 then
...;
end if;
if not VILLKOR_1 and not VILLKOR_2 and VILLKOR_3 then
...;
end if;
|
if VILLKOR_1 then
...;
elsif VILLKOR_2 then
...;
elsif VILLKOR_3 then
...;
end if;
|
if A = B or C = D then
|
if (A = B) or (C = D) then
|
if (X > Y) or (X = Y) then
|
if X >= Y then
|
if VILLKOR then
null; -- Tom sats som inte gör något.
else
...;
end if;
|
if not VILLKOR then
...;
end if;
|
if VILLKOR then
...;
else
null; -- Tom sats som inte gör något.
end if;
|
if VILLKOR then
...;
end if;
|
if (A = 1) or (A = 2) or (A = 3) or (A = 4) then
|
if A in 1 .. 4 then
|
if (A < 1) and (A > 4) then
|
if A not in 1 .. 4 then
|
if Character'Pos(Ch) = 48 then
|
if Ch = '0' then
|
Vilken loop skall jag använda?
När det gäller val av upprepningssatser är det väldigt ofta så att
man väljer en väg som gör att man kommer till program som är lite
"knasigt" uppbyggt. Det finns ofta bättre sätt då. Vi tar några
exempel där man "bygger" en annan variant av "loop"-sats utan att
man kanske tänker på detta.
Innan vi tar dessa så tar vi några frågor som man kan ställa sig
för att komma mer rätt på en gång i sina val av iterationssatser
(upprepningssatser).
- Skall detta upprepas oändligt många gånger (eller tills
strömmen bryts)?
Detta ger direkt "loop".
- Vet du antal gånger du skall upprepa detta (eller kan räkna
ut det)?
Detta ger direkt "for".
- Vet du att du skall utföra detta minst en gång?
Detta ger direkt "loop".
- Annars!
Detta ger "while".
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Att bygga en "while" m.h.a. en "loop".
loop
if VILLKOR then
exit;
end if;
...;
end loop;
|
while not VILLKOR then
...;
end loop;
|
-- Att bygga en "while" m.h.a. en "loop".
if VILLKOR_1 then
loop
...;
if not VILLKOR_1 then
exit;
end if;
end loop;
end if;
|
while VILLKOR_1 then
...;
end loop;
|
-- Att bygga en "for" m.h.a. en "loop".
i := 1;
loop
...;
i := i + 1;
if 1 > 10 then
exit;
end if;
end loop;
|
for i in 1 .. 10 loop
...;
end loop;
|
-- Att bygga en "for" m.h.a. en "while".
i := 1;
while i <= 10 loop
...;
i := i + 1;
end loop;
|
for i in 1 .. 10 loop
...;
end loop;
|
-- Varför ha samma kod på två ställen
-- (två "Put" och "Get") som gör samma
-- sak (markerat med "-- ***" nedan)?
-- Dessutom i detta fall varför ha
-- två Get för att läsa ETT tal?
Put("Mata in: "); -- ***
Get(X); -- ***
while X < 0 loop
Error_Message;
Put("Mata in: "); -- ***
Get(X); -- ***
end loop;
|
-- Fel tänkt! Se även under fliken
-- "Duplicering av kod" nedan.
loop
Put("Mata in: "); -- ***
Get(X); -- ***
if X >= 0 then
exit;
end if;
Error_Message;
end loop;
-- Eller en variant utan "if"
-- (med "exit"-variant).
loop
Put("Mata in: ");
Get(X);
exit when X >= 0;
Error_Message;
end loop;
|
Felaktigt sätt att använda en "for"-sats
Det dyker ibland upp kod där man ser att någon/några av satserna
inuti en "for"-sats modifierar antingen själva styrvariabeln eller
något som påverkar någon av gränserna för det intervall som
"for"-satsen skall agera över. Detta kan ställa till det mycket om
man inte vet vad man gör. Det är dessutom så att detta behandlas
olika i olika programspråk. Vi säger därför att detta inte
är ok i vår kurs.
I nedanstående fall skall man alltså fundera på en annan lösning
av problemet.
Hur man inte bör skriva
|
-- Att försöka ändra styrvariabeln.
for I in 1 .. 5 loop
...;
I := 1;
...;
end loop;
|
-- Att försöka ändra minvärdet.
for I in A .. B loop
...;
A := B + 1;
...;
end loop;
|
-- Att försöka ändra maxvärdet.
for I in A .. B loop
...;
B := B + 1;
...;
end loop;
|
Onaturligt sätt att anropa operatorer
En operator är en "form av funktion" som anropas lite
speciellt. Det "går" att anropa dessa på "samma sätt" som
en funktion, MEN detta är INTE något man gör i det generella
fallet. Det är väldigt specifika fall detta görs och det skall ni
inte göra i denna kurs.
OBS! Tänk så här: "Bara för att det går behöver man inte göra
det (om det är en sämre variant)".
Hur man inte bör skriva
|
Hur man bör skriva
|
if ">"("Love", "Hate") then
|
if "Love" > "Hate" then
|
A := "+"(5, 3);
|
A := 5 + 3;
|
De lite speciella "unära" operatorerna som anger tecknet (+/-) för
t.ex. heltal.
Hur man inte bör skriva
|
Hur man bör skriva
|
A := "+"(5);
A := "-"(5);
|
A := +5;
A := -5;
|
"Onödigt" att mellanlagra data
Om man tittar på vad en funktion eller en operator gör så kan man
se att det är onödigt att mellanlagra det resultat som kommer
tillbaka om man inte skall använda detta flera gånger (i vissa
fall är det bra att stoppa in datat i en variabel, men det finns
också nackdelar med detta i vissa fall).
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Varför ha 4 variabler istället för 1?
A := Sin(X);
B := Sin(Y);
C := Cos(Z);
Sum := A + B + C;
|
Sum := Sin(X) + Sin(Y) + Cos(Z);
|
-- Onödig lagring av literaler.
I := 1;
Put(I);
Ch := 'A';
Put(Ch);
|
Put(1);
Put('A');
|
-- Varför mellanlagra funktionsvärdet?
A := Factorial(N);
Put(A);
|
Put(Factorial(N));
|
-- Även t.ex. "if" klarar av att hantera uttryck ...
A := Factorial(N);
if A = 6 then
Flag := A > B;
if Flag then
|
if Factorial(N) = 6 then
if A > B then
|
Put(Integer(Sin(X) * 3.2 / Cos(Y)) mod 4);
|
-- Ibland vill man dock mellanlagra data för att kunna
-- få bra identifierare som beskriver vad det är man
-- beräknat.
Good_Name := Integer(Sin(X) * 3.2 / Cos(Y)) mod 4;
Put(Good_Name);
|
-- Utskrifter av beräknade värden.
Put(First_price);
Put(First_price * Procentage);
Put(First_price + First_price * Procentage);
|
-- Det bli tydligare kod om man namnger de
-- olika värdena man beräknat.
Extra := First_price * Procentage;
Total := First_price + Extra;
Put(First_price);
Put(Extra);
Put(Total);
|
-- Beräkninger eller delberäkningar som man
-- sen vill användare vid ett flertal tillfällen.
Put((Sin(X) + 33.2) * Cos(Y) - 4.5);
Put((Sin(X) + 33.2) * Cos(Y) + 4.5);
|
Delresultat := (Sin(X) + 33.2) * Cos(Y) + 4.5;
Put(Delresultat - 4.5);
Put(Delresultat + 4.5);
|
function My_Function(X, Y : in Float) return Float is
begin
return Sqrt(X * X + Y * Y) / 100.0;
end My_function;
|
-- Namngivning av returvärde ökar läsbarheten om
-- beräkningen är svårförståelig.
function My_Function(X, Y : in Float) return Float is
Length_In_Meters : Float;
begin
Length_In_Meters := Sqrt(X * X + Y * Y) / 100.0;
return Length_In_Meters;
end My_function;
|
Duplicering av kod
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Varför ha samma kod på flera ställen
-- som gör samma sak (markerat med
-- "-- ***" nedan)?
Put("Mata in: "); -- ***
Get(X); -- ***
Put("Mata in: "); -- ***
Get(X); -- ***
Put("Mata in: "); -- ***
Get(X); -- ***
|
-- Man bygger om detta till en "for".
for I in 1 ..3 loop
Put("Mata in: "); -- ***
Get(X); -- ***
end loop;
|
-- Varför ha samma kod på två ställen
-- (två "Put" och "Get") som gör samma
-- sak (markerat med "-- ***" nedan)?
-- Dessutom i detta fall varför ha
-- två Get för att läsa ETT tal?
Put("Mata in: "); -- ***
Get(X); -- ***
while X < 0 loop
Error_Message;
Put("Mata in: "); -- ***
Get(X); -- ***
end loop;
|
-- Man bygger om detta till en "loop".
loop
Put("Mata in: "); -- ***
Get(X); -- ***
exit when X >= 0;
Error_Message;
end loop;
|
-- Varför ha samma kod på två ställen
-- (två "Put" och "Get") som gör samma
-- sak (markerat med "-- ***" nedan)?
-- I detta fall inte enkelt att bygga om.
-- till en "loop" av något slag.
loop
Put("Mata in: "); -- ***
Get(X); -- ***
...;
Put("Mata in: "); -- ***
Get(X); -- ***
...;
end loop;
|
-- Gör ett underprogram som löser
-- denna del i koden och anropa
-- underprogrammet två gånger.
-- Antag att underprogrammet heter
-- "Skriv_Ut_Ledtext_Och_Mata_In".
loop
Skriv_Ut_Ledtext_Och_Mata_In(X);
...;
Skriv_Ut_Ledtext_Och_Mata_In(X);
...;
end loop;
|
-- Samma sak i två eller flera grenar
-- i en "if"-sats.
if ... then
Put("En text");
Put("Lite till");
Put("Avslutning");
else
Put("En text");
Put("Avslutning");
end if;
-- Detta kan t.ex. vara intressant när man
-- skall skriv ut om något or ok eller ej.
if Sanning then
Put("Det är sant");
else
Put("Det är inte sant");
end if;
|
-- Man har bara kvar det som skiljer.
Put("En text");
if ... then
Put("Lite till");
end if;
Put("Avslutning");
-- Det är bara "inte" som skiljer. I vårt lilla
-- "minikosmos" kan detta var rimligt.
Put("Det är");
if not Sanning then
Put(" inte");
end if;
Put(" sant");
-- Detta kan dras till absurdum så att man tar
-- detta ner till teckennivå, men det är alltså
-- inte meningen. T.ex. behöver ni inte ta delar
-- av ord beroende på böjningsformer, men det
-- skulle kunna vara intressant i vissa fall
-- (i "verkligheten").
|
-- Utskrift av samma sträng flera gånger.
begin
Put("#################################");
Put("Detta är mitt program");
Put("#################################");
...;
Put("#################################");
...;
Put("#################################");
|
-- Flytta innehållet till konstant.
Separator : constant String :=
"#################################";
begin
Put(Separator);
Put("Detta är mitt program");
Put(Separator);
...;
Put(Separator);
...;
Put(Separator);
|
Fullständig uppräkning
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Flera if-satser (eller elsif)
-- som jämför samma variabel.
if I = 1 then
...;
elsif I = 3 then
...;
elsif ... then
...;
end if;
-- Ett intervall av data.
if N = 1 or N = 2 or N = 3 or N = 4 then
-- Lite spridda data (i detta fall
-- udda talen mellan 1 och 7).
if N = 1 or N = 3 or N = 5 or N = 7 then
-- Lite spridda data.
if N = 1 or N = 3 or N = 5 or N = 8 then
...;
else
...;
end if;
-- Udda talen mellan 1 och 7 igen.
if N = 1 or N = 3 or N = 5 or N = 7 then
|
-- Använd "case" istället för "if".
case I is
when 1 =>
...;
when 3 =>
...;
when others =>
...;
end case;
-- Använd intervall istället.
if N in 1 .. 4 then
-- Kanske tänk annorlunda.
if (N in 1 .. 7) and (N mod 2 = 1) then
-- Använd "case" istället för "if".
case N is
when 1 | 3 | 5 | 8 =>
...;
when others =>
...;
end case;
-- Skapa ett underprogram.
if Udda_Tal_Mellan_1_Och_7(N) then
|
I : Integer;
begin
Put("Välj ett nummer på en veckodag ");
Get(I);
Put("Den dagen heter: ");
-- Denna uppräkning vill vi inte behöva göra
-- varje gång namnet på en dag skrivs ut.
if I = 1 then
Put("Mon");
elsif I = 2 then
Put("Tue");
elsif I = 3 then
Put("Wed");
elsif I = 4 then
Put("Thu");
elsif I = 5 then
Put("Fri");
elsif I = 6 then
Put("Sat");
elsif I = 7 then
Put("Sun");
end if;
|
-- Detta fält kan vi återanvända överallt
-- i koden, istället för att göra uppräkningen
-- varje gång vi behöver den
Veckodagar : constant array (1 .. 7) of String(1 .. 3) :=
(1 => "Mon",
2 => "Tue",
3 => "Wed",
4 => "Thu",
5 => "Fri",
6 => "Sat",
7 => "Sun");
I : Integer;
begin
Put("Välj ett nummer på en veckodag :");
Get(I);
Put("Den dagen heter: ");
Put(Veckodagar(I));
|
-- Överkomplicerad lösning för att undvika
-- "kodduplicering" vilket istället leder
-- till "fullständig uppräkning"
for I in 1..2 loop
Put("Mata in ett heltal: ");
if I = 1 then
Get(I1);
else
Get(I2);
end if;
end loop;
|
Put("Mata in ett heltal: ");
Get(I1);
Put("Mata in ett heltal: ");
Get(I2);
|
Parameterlistor
Här finns det två sorts parameterlistor
- Den formella parameterlistan (i definitionen [eller
deklarationen] av underprogrammet.
- Den aktuella parameterlistan. Den som är i själva anropet av
underprogrammet (t.ex. i huvudprogrammet).
Hur man inte bör skriva
|
Hur man bör skriva
|
Put(I, 2);
Put(F, 2, 3, 0);
|
Put(I, Width => 2);
Put(F, Fore => 2, Aft, 3, Exp => 0);
|
Subprog(A,B,C,D,E);
|
Subprog(A, B, C, D, E);
-- Om det blir långa rader kan man bryta efter ','.
Subprog(A, B, C,
D, E);
|
procedure Subprog(P_1:in Type_1;P_2,P_3:in out Type_2) is
procedure Subprog(P_1:in Type_1;
P_2, P_3:in out Type_2;
P_4:out Type_1;
P_5:out Type_3) is
procedure Subprog(P_1 : in Type_1;
P_2, P_3 : in out Type_2;
P_4 : out Type_1;
P_5 : out Type_3) is
procedure Subprog(P_1 : in Type_1;
P_4 : out Type_1;
P_5 : out Type_3) is
function Subprog(P_1:Type_1; P_2,P_3:Type_2) return Type_3 is
function Subprog(P_1:in Type_1;P_2,P_3:in Type_2) return Type_3 is
function Subprog(P_1 : out Type_1) return Type_2 is
|
-- Mycket mer läsbart.
procedure Subprog(P_1 : in Type_1;
P_2, P_3 : in out Type_2;
P_4 : out Type_1;
P_5 : out Type_3) is
procedure Subprog(P_1 : in Type_1;
P_4 : out Type_1;
P_5 : out Type_3) is
function Subprog(P_1 : in Type_1;
P_2, P_3 : in Type_2) return Type_3 is
function Subprog(P_1 : in Type_1;
P_2, P_3 : in Type_2)
return Type_3 is
-- Inte "out" i någon form i funktioner
-- (även om det går är det inte ok i kursen).
|
Många rader kod
I kursen eftersträvar vi att varje program är kortare än 20 rader (max ~20
satser mellan begin och) för ökad läsbarhet. Detta uppnås genom att dela
upp program i underprogram.
Hur man inte bör skriva
|
Hur man bör skriva
|
-- Ett långt och svårläst program.
procedure Exempel is
I : Integer;
N1, N2 : Integer;
begin
Put("Mata in ett positivt heltal: ");
loop
Get(I);
exit when I > 0;
Put_Line("Ej positivt...");
end loop;
Put("Ditt tal i kvadrat: ");
Put(I * I, Width => 0);
New_Line;
Put("Första (ditt heltal) fibbonaccitalen: ");
N1 := 1;
N2 := 1;
Put(1, Width => 0);
for J in 2 .. I loop
Put(" ");
Put(N2, Width => 0);
I := N1;
N1 := N2;
N2 := I + N2;
end loop;
New_Line;
Put_Line("En fin liten kvadrat: ");
for Y in 1 .. I loop
Put(" ");
for X in 1 .. I loop
Put("##");
end loop;
New_Line;
end loop;
end Exempel;
|
-- Dela upp programmet i underprogram.
procedure Exempel is
procedure Get_Positive(...) is
...;
begin
...;
end Get_Positive;
...; -- Resterande underprogram
I : Integer;
begin
-- Lättare att se vad programmet gör.
Get_Positive(I);
Put_Square_Of(I);
Put_Fibonacci(I);
Put_Square(I);
end Exempel;
|
Placering av underprogram
Att ha underprogram inuti underprogram ger ibland en fördel, MEN
det är oftast så att man får både problem med att hitta i sin
programkod och att få det "snyggt" rent textuellt i sitt program.
Det är oftast bättre att skriva underprogrammen "ovanför" istället
för "inuti". OBS! Självklart skall alla underprogram ligga "inuti"
huvudprogrammet (i Ada).
Hur man inte bör skriva
|
Hur man bör skriva
|
procedure Main is
procedure Level_1 is
procedure Level_2 is
procedure Level_3 is
procedure Level_4 is
begin
...;
end Level_4;
begin
Level_4;
end Level_3;
begin
Level_3;
end Level_2;
begin
Level_2;
end Level_1;
begin
Level_1;
end Main;
|
procedure Main is
--------------------
procedure Level_4 is
begin
...;
end Level_4;
--------------------
procedure Level_3 is
begin
Level_4;
end Level_3;
--------------------
procedure Level_2 is
begin
Level_3;
end Level_2;
--------------------
procedure Level_1 is
begin
Level_2;
end Level_1;
--------------------
begin
Level_1;
end Main;
|
Undantagshantering
Vid undantagshantering ska endast de delar som reser undantag
ligga mellan egendefinerade "begin" och "exception".
Att introducera nya "begin" och "end" ska undvikas om detta inte behövs.
Hur man inte bör skriva
|
Hur man bör skriva
|
procedure Exempel is
begin
begin
-- början av programmet
Do_Stuff(...);
-- Koden som kan resa undantag
My_Function(...);
exception
when Name_Error =>
-- Hantering av själva undantaget
Print_Error_Message(...);
-- Fortsättningen av programmet
Do_More_Stuff(...);
end;
end Exempel;
|
procedure Exempel is
begin
-- början av programmet
Do_Stuff(...);
begin
-- Koden som kan resa undantag
My_Function(...);
exception
when Name_Error =>
-- Hantering av själva undantaget
Print_Error_Message(...);
end;
-- Fortsättningen av programmet
Do_More_Stuff(...);
end Exempel;
|
Saker som är utanför kursen
Nedan följer en lista över de saker vi upptäckt som är utanför
kursen. Alltså sådant som inte tas upp i kursen och därför inte är
tillåtet att användas. Denna lista kommer fyllas på allt eftersom
fler saker upptäcks.
- Paketet Ada.Strings.Fixed
- Paketet Ada.Strings.Unbounded
- Expression functions
Sidansvarig: Torbjörn Jonsson
Senast uppdaterad: 2023-08-21